#include "core/random.hpp"

/**
 * \file
 * \ingroup random
 * \brief RNGs implementation.
 */

namespace cas
{
    SLOG_COMPONENT_DEFINE("RNG");

    template <typename T>
    MersenneTwisterRNG<T>::MersenneTwisterRNG()
    {
        SLOG_FUNCTION_NOARGS();
        this->seed = RNG<T>::DefaultSeed;
        gen.seed(this->seed);
    }

    template <typename T>
    MersenneTwisterRNG<T>::MersenneTwisterRNG(rng_seed_t seed)
    {
        SLOG_FUNCTION_NOARGS();
        setSeed(seed);
    }

    template <typename T>
    MersenneTwisterRNG<T>::MersenneTwisterRNG(const MersenneTwisterRNG<T> &mt)
    {
        SLOG_FUNCTION(typeid(mt).name());
        this->seed = mt.seed;
        this->gen = mt.gen;
    }

    template <typename T>
    void MersenneTwisterRNG<T>::setSeed(rng_seed_t seed)
    {
        SLOG_FUNCTION(seed);
        this->seed = seed;
        gen.seed(this->seed);
    }

    UniformRealRND::UniformRealRND()
    {
        SLOG_FUNCTION_NOARGS();
        rng = std::make_shared<MersenneTwisterRNG<uint64_t>>();
        uni.param(decltype(uni)::param_type(0.0, 1.0));
    }

    void UniformRealRND::setParam(const double &a, const double &b)
    {
        SLOG_FUNCTION(a << b);
        uni.param(decltype(uni)::param_type(a, b));
    }

    UniformInt64RND::UniformInt64RND()
    {
        SLOG_FUNCTION_NOARGS();
        rng = std::make_shared<MersenneTwisterRNG<uint64_t>>();
        uni.param(decltype(uni)::param_type(0.0, 1.0));
    }

    UniformInt64RND::UniformInt64RND(const UniformInt64RND &u)
    {
        SLOG_FUNCTION(typeid(u).name());
        this->rng = u.rng;
        this->uni = u.uni;
    }

    void UniformInt64RND::setParam(const int64_t &a, const int64_t &b)
    {
        SLOG_FUNCTION(a << b);
        uni.param(decltype(uni)::param_type(a, b));
    }
}
